#pragma once

#include <cmath>

namespace matsu
{
	template<typename T>
	class Vector2 {
	public:
		Vector2();
		Vector2(T x, T y);
		Vector2(T *ptr);
		Vector2(const T *ptr);

		T* pointer();

		//operator overloading
		bool operator==(const Vector2<T> &o) const;
		bool operator!=(const Vector2<T> &o) const;
		Vector2<T> operator+(const Vector2<T> &o) const;
		Vector2<T> operator-(const Vector2<T> &o) const;
		Vector2<T> operator*(T t) const;
		Vector2<T> operator/(T t) const;
		Vector2<T>& operator+=(const Vector2<T> &o);
		Vector2<T>& operator-=(const Vector2<T> &o);
		Vector2<T>& operator*=(T t);
		Vector2<T>& operator/=(T t);

		Vector2<T> normal() const;
		void normalize();
		T size() const;
		T sizeSquare() const;

		Vector2<T> lerp(float t, const Vector2<T>& v) const;
	public:
		T x;
		T y;
	};

	template<typename T>
	class Vector3 {
	public:
		Vector3();
		Vector3(T x, T y, T z);
		Vector3(T *ptr);
		Vector3(const T *ptr);

		T* pointer();

		//operator overloading
		void normalize();
		Vector3 normal() const;
		Vector3 cross(const Vector3& v) const;
		T dot(const Vector3& v) const;
		Vector3 operator+(const Vector3& v) const;
		void operator+=(const Vector3& v);
		void operator-=(const Vector3& v);
		void operator/=(T s);
		Vector3 operator-(const Vector3& v) const;
		Vector3 operator-() const;
		Vector3 operator*(T s) const;
		Vector3 operator/(T s) const;
		bool operator==(const Vector3& v) const;
		Vector3 lerp(float t, const Vector3& v) const;

	public:
		T x;
		T y;
		T z;
	};

	template <typename T>
	class Vector4 {
	public:
		Vector4();
		Vector4(T x, T y, T z, T w);
		Vector4(T* ptr);
		Vector4(Vector3<T> v);
		Vector4(const T* ptr);
		T dot(const Vector4& v) const;
		Vector4(const Vector3<T> &v, T w);
		Vector4 lerp(float t, const Vector4& v) const;
		T* pointer();

		bool operator==(const Vector4& v) const;
		bool operator!=(const Vector4& v) const;

		Vector3<T> toVec3() const;
		Vector2<T> toVec2() const;

		T x;
		T y;
		T z;
		T w;
	};


	//typedef
	typedef Vector2<int> ivec2;
	typedef Vector2<float> vec2;
	typedef Vector3<int> ivec3;
	typedef Vector3<float> vec3;
	typedef Vector4<int> ivec4;
	typedef Vector4<float> vec4;
}

#include "MTVector.hpp"
